return ret;
}
-static inline int HYPERVISOR_net_io_op(unsigned int op, unsigned int idx)
+static inline int HYPERVISOR_net_io_op(netop_t *op)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_net_io_op),
- "b" (op), "c" (idx) );
+ "b" (op) );
return ret;
}
#include <os.h>
/* Offsets in start_info structure */
-#define MOD_START 4
-#define MOD_LEN 8
+#define MOD_START 20
+#define MOD_LEN 24
.globl _start, shared_info
*/
void start_kernel(start_info_t *si)
{
- int i;
-
/* Copy the start_info struct to a globally-accessible area. */
memcpy(&start_info, si, sizeof(*si));
printk(" pt_base: %p", (void *)si->pt_base);
printk(" mod_start: 0x%lx\n", si->mod_start);
printk(" mod_len: %lu\n", si->mod_len);
+#if 0 /* XXX Change to use NETOP_GET_VIF_INFO and BLOCK_IO_OP_RING_ADDRESS */
printk(" net_rings: ");
for (i = 0; i < MAX_DOMAIN_VIFS; i++) {
printk(" %lx", si->net_rings[i]);
}; printk("\n");
printk(" blk_ring: 0x%lx\n", si->blk_ring);
+#endif
printk(" dom_id: %d\n", si->dom_id);
printk(" flags: 0x%lx\n", si->flags);
printk(" cmd_line: %s\n", si->cmd_line ? (const char *)si->cmd_line : "NULL");
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
static unsigned long virt_startinfo_addr;
-static unsigned long startinfo_frame;
static char *argv0 = "internal_domain_build";
virt_startinfo_addr =
virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
- startinfo_frame = page_array[alloc_index-1];
- start_info = map_pfn(startinfo_frame);
+ start_info = map_pfn(page_array[alloc_index-1]);
memset(start_info, 0, sizeof(*start_info));
start_info->pt_base = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
start_info->mod_start = initrd_addr;
ctxt->failsafe_callback_cs = FLAT_RING1_CS;
ctxt->failsafe_callback_eip = 0;
- ctxt->start_info_frame = startinfo_frame;
-
launch_op.u.builddomain.domain = domain_id;
launch_op.u.builddomain.num_vifs = atoi(argv[3]);
p->failsafe_selector;
op.u.getdomaininfo.ctxt.failsafe_callback_eip =
p->failsafe_address;
- op.u.getdomaininfo.ctxt.start_info_frame =
- p->thread.start_info_frame;
}
}
read_unlock_irqrestore(&tasklist_lock, flags);
*/
int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
{
- start_info_t *startinfo;
unsigned long phys_l2tab;
- net_ring_t *shared_rings;
- net_vif_t *net_vif;
- int i;
if ( (p->flags & PF_CONSTRUCTED) )
return -EINVAL;
p->event_address = builddomain->ctxt.event_callback_eip;
p->failsafe_selector = builddomain->ctxt.failsafe_callback_cs;
p->failsafe_address = builddomain->ctxt.failsafe_callback_eip;
- p->thread.start_info_frame = builddomain->ctxt.start_info_frame;
/* NB. Page base must already be pinned! */
phys_l2tab = builddomain->ctxt.pt_base;
/* Set up the shared info structure. */
update_dom_time(p->shared_info);
- startinfo = (start_info_t *)
- map_domain_mem(p->thread.start_info_frame << PAGE_SHIFT);
-
/* Add virtual network interfaces and point to them in startinfo. */
while ( builddomain->num_vifs-- > 0 )
- {
- net_vif = create_net_vif(p->domain);
- shared_rings = net_vif->shared_rings;
- if (!shared_rings) panic("no network ring!\n");
- }
-
- for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
- {
- if ( p->net_vif_list[i] == NULL ) continue;
- startinfo->net_rings[i] =
- virt_to_phys(p->net_vif_list[i]->shared_rings);
- memcpy(startinfo->net_vmac[i],
- p->net_vif_list[i]->vmac, ETH_ALEN);
- }
-
- /* Add block io interface */
- startinfo->blk_ring = virt_to_phys(p->blk_ring_base);
-
- unmap_domain_mem(startinfo);
+ (void)create_net_vif(p->domain);
p->flags |= PF_CONSTRUCTED;
l2_pgentry_t *l2tab, *l2start;
l1_pgentry_t *l1tab = NULL, *l1start = NULL;
struct pfn_info *page = NULL;
- net_ring_t *shared_rings;
- net_vif_t *net_vif;
/* Sanity! */
if ( p->domain != 0 ) BUG();
update_dom_time(p->shared_info);
p->shared_info->domain_time = 0;
- /* DOM0 can't be stopped/started, so no need for an ongoing s.i. frame. */
- p->thread.start_info_frame = 0;
-
virt_startinfo_address = (start_info_t *)
(virt_load_address + ((alloc_index - 1) << PAGE_SHIFT));
virt_stack_address = (unsigned long)virt_startinfo_address;
}
/* Add virtual network interfaces and point to them in startinfo. */
- while (num_vifs-- > 0) {
- net_vif = create_net_vif(dom);
- shared_rings = net_vif->shared_rings;
- if (!shared_rings) panic("no network ring!\n");
- }
-
- for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
- {
- if ( p->net_vif_list[i] == NULL ) continue;
- virt_startinfo_address->net_rings[i] =
- virt_to_phys(p->net_vif_list[i]->shared_rings);
- memcpy(virt_startinfo_address->net_vmac[i],
- p->net_vif_list[i]->vmac, ETH_ALEN);
- }
-
- /* Add block io interface */
- virt_startinfo_address->blk_ring = virt_to_phys(p->blk_ring_base);
+ while ( num_vifs-- > 0 )
+ (void)create_net_vif(dom);
dst = virt_startinfo_address->cmd_line;
if ( cmdline != NULL )
}
break;
+ case BLOCK_IO_OP_RING_ADDRESS:
+ op.u.ring_mfn = virt_to_phys(p->blk_ring_base) >> PAGE_SHIFT;
+ ret = copy_to_user(u_block_io_op, &op, sizeof(op)) ? -EFAULT : 0;
+ break;
+
default:
ret = -ENOSYS;
}
};
struct thread_struct {
- unsigned long start_info_frame; /* Filled in on DOM0_START */
unsigned long esp1, ss1;
/* Hardware debugging registers */
unsigned long debugreg[8]; /* %%db0-7 debug registers */
long set_fast_trap(struct task_struct *p, int idx);
#define INIT_THREAD { \
- 0, 0, 0, \
+ 0, 0, \
{ [0 ... 7] = 0 }, /* debugging registers */ \
{ { 0, }, }, /* 387 state */ \
0x20, { 0, 0 }, /* DEFAULT_FAST_TRAP */ \
unsigned long event_callback_eip;
unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
unsigned long failsafe_callback_eip;
- unsigned long start_info_frame; /* Page frame containing s.i. */
} full_execution_context_t;
#define MAX_CMD_LEN 256
* NB. We expect that this struct is smaller than a page.
*/
typedef struct start_info_st {
- /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
- unsigned long pt_base; /* VIRTUAL address of page directory. */
- unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */
- unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
unsigned long nr_pages; /* total pages allocated to this domain. */
unsigned long shared_info; /* MACHINE address of shared info struct.*/
- unsigned int dom_id; /* Domain identifier. */
+ unsigned long dom_id; /* Domain identifier. */
unsigned long flags; /* SIF_xxx flags. */
- unsigned long net_rings[MAX_DOMAIN_VIFS]; /* MACHINE address of ring.*/
- unsigned char net_vmac[MAX_DOMAIN_VIFS][6]; /* MAC address of VIF. */
- unsigned long blk_ring; /* MACHINE address of blkdev ring. */
+ /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
+ unsigned long pt_base; /* VIRTUAL address of page directory. */
+ unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */
+ unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
unsigned char cmd_line[1]; /* Variable-length options. */
} start_info_t;
#define NETOP_PUSH_BUFFERS 0 /* Notify Xen of new buffers on the rings. */
#define NETOP_FLUSH_BUFFERS 1 /* Flush all pending request buffers. */
#define NETOP_RESET_RINGS 2 /* Reset ring indexes on a quiescent vif. */
+#define NETOP_GET_VIF_INFO 3 /* Query information for this vif. */
+typedef struct netop_st {
+ unsigned int cmd; /* NETOP_xxx */
+ unsigned int vif; /* VIF index */
+ union {
+ struct {
+ unsigned long ring_mfn; /* Page frame containing net_ring_t. */
+ unsigned char vmac[6]; /* Virtual Ethernet MAC address. */
+ } get_vif_info;
+ } u;
+} netop_t;
+
typedef struct tx_req_entry_st
{
/* Block I/O trap operations and associated structures.
*/
-#define BLOCK_IO_OP_SIGNAL 0 /* let xen know we have work to do */
-#define BLOCK_IO_OP_ATTACH_VBD 1 /* attach a VBD to a given domain */
-#define BLOCK_IO_OP_RESET 2 /* reset ring indexes on quiescent i/f */
+#define BLOCK_IO_OP_SIGNAL 0 /* let xen know we have work to do */
+#define BLOCK_IO_OP_ATTACH_VBD 1 /* attach a VBD to a given domain */
+#define BLOCK_IO_OP_RESET 2 /* reset ring indexes on quiescent i/f */
+#define BLOCK_IO_OP_RING_ADDRESS 3 /* returns machine address of I/O ring */
typedef struct _extent {
u16 raw_device;
unsigned long cmd;
union
{
- /* no entry for BLOCK_IO_OP_SIGNAL */
+ /* no entry for BLOCK_IO_OP_SIGNAL */
vbd_attach_t attach_info;
- /* no entry for BLOCK_IO_OP_RESET */
+ /* no entry for BLOCK_IO_OP_RESET */
+ unsigned long ring_mfn;
}
u;
} block_io_op_t;
#include <linux/brlock.h>
#include <linux/init.h>
#include <linux/module.h>
-
#include <linux/event.h>
#include <asm/domain_page.h>
#include <asm/pgalloc.h>
-
+#include <asm/io.h>
#include <xeno/perfc.h>
#define BUG_TRAP ASSERT
* Called from guest OS to notify updates to its transmit and/or receive
* descriptor rings.
*/
-long do_net_io_op(unsigned int op, unsigned int idx)
+long do_net_io_op(netop_t *uop)
{
+ netop_t op;
net_vif_t *vif;
long ret;
perfc_incr(net_hypercalls);
- if ( (vif = current->net_vif_list[idx]) == NULL )
+ if ( copy_from_user(&op, uop, sizeof(op)) )
+ return -EFAULT;
+
+ if ( (op.vif >= MAX_DOMAIN_VIFS) ||
+ ((vif = current->net_vif_list[op.vif]) == NULL) )
return -EINVAL;
- switch ( op )
+ switch ( op.cmd )
{
case NETOP_PUSH_BUFFERS:
ret = get_bufs_from_vif(vif);
spin_unlock_irq(&vif->tx_lock);
break;
+ case NETOP_GET_VIF_INFO:
+ op.u.get_vif_info.ring_mfn =
+ virt_to_phys(vif->shared_rings) >> PAGE_SHIFT;
+ memcpy(op.u.get_vif_info.vmac, vif->vmac, ETH_ALEN);
+ ret = copy_to_user(uop, &op, sizeof(op)) ? -EFAULT: 0;
+ break;
+
default:
ret = -EINVAL;
break;
if ( HYPERVISOR_block_io_op(&op) != 0 )
printk(KERN_ALERT "Possible blkdev trouble: couldn't reset ring\n");
- set_fixmap(FIX_BLKRING_BASE, start_info.blk_ring);
+ op.cmd = BLOCK_IO_OP_RING_ADDRESS;
+ (void)HYPERVISOR_block_io_op(&op);
+
+ set_fixmap(FIX_BLKRING_BASE, op.u.ring_mfn << PAGE_SHIFT);
blk_ring = (blk_ring_t *)fix_to_virt(FIX_BLKRING_BASE);
blk_ring->req_prod = blk_ring->resp_prod = resp_cons = req_prod = 0;
static int network_open(struct net_device *dev)
{
struct net_private *np = dev->priv;
- int i;
+ netop_t netop;
+ int i, ret;
- if ( HYPERVISOR_net_io_op(NETOP_RESET_RINGS, np->idx) != 0 )
+ netop.cmd = NETOP_RESET_RINGS;
+ netop.vif = np->idx;
+ if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 )
+ {
printk(KERN_ALERT "Possible net trouble: couldn't reset ring idxs\n");
+ return ret;
+ }
+
+ netop.cmd = NETOP_GET_VIF_INFO;
+ netop.vif = np->idx;
+ if ( (ret = HYPERVISOR_net_io_op(&netop)) != 0 )
+ {
+ printk(KERN_ALERT "Couldn't get info for vif %d\n", np->idx);
+ return ret;
+ }
+
+ memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN);
set_fixmap(FIX_NETRING0_BASE + np->net_ring_fixmap_idx,
- start_info.net_rings[np->idx]);
+ netop.u.get_vif_info.ring_mfn << PAGE_SHIFT);
np->net_ring = (net_ring_t *)fix_to_virt(
FIX_NETRING0_BASE + np->net_ring_fixmap_idx);
np->net_idx = &HYPERVISOR_shared_info->net_idx[np->idx];
struct net_private *np = dev->priv;
struct sk_buff *skb;
unsigned int end = RX_RING_ADD(np->rx_resp_cons, RX_MAX_ENTRIES);
+ netop_t netop;
if ( ((i = np->net_idx->rx_req_prod) == end) ||
(np->state != STATE_ACTIVE) )
/* Batch Xen notifications. */
if ( np->rx_bufs_to_notify > (RX_MAX_ENTRIES/4) )
{
- HYPERVISOR_net_io_op(NETOP_PUSH_BUFFERS, np->idx);
+ netop.cmd = NETOP_PUSH_BUFFERS;
+ netop.vif = np->idx;
+ (void)HYPERVISOR_net_io_op(&netop);
np->rx_bufs_to_notify = 0;
}
}
{
unsigned int i, id;
struct net_private *np = (struct net_private *)dev->priv;
+ netop_t netop;
if ( np->tx_full )
{
/* Only notify Xen if there are no outstanding responses. */
mb();
if ( np->net_idx->tx_resp_prod == i )
- HYPERVISOR_net_io_op(NETOP_PUSH_BUFFERS, np->idx);
+ {
+ netop.cmd = NETOP_PUSH_BUFFERS;
+ netop.vif = np->idx;
+ (void)HYPERVISOR_net_io_op(&netop);
+ }
return 0;
}
int network_close(struct net_device *dev)
{
struct net_private *np = dev->priv;
+ netop_t netop;
np->state = STATE_SUSPENDED;
wmb();
netif_stop_queue(np->dev);
- HYPERVISOR_net_io_op(NETOP_FLUSH_BUFFERS, np->idx);
+ netop.cmd = NETOP_FLUSH_BUFFERS;
+ netop.vif = np->idx;
+ (void)HYPERVISOR_net_io_op(&netop);
while ( (np->rx_resp_cons != np->net_idx->rx_req_prod) ||
(np->tx_resp_cons != np->net_idx->tx_req_prod) )
int i, fixmap_idx=-1, err;
struct net_device *dev;
struct net_private *np;
+ netop_t netop;
INIT_LIST_HEAD(&dev_list);
for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
{
- if ( start_info.net_rings[i] == 0 )
+ /* If the VIF is invalid then the query hypercall will fail. */
+ netop.cmd = NETOP_GET_VIF_INFO;
+ netop.vif = i;
+ if ( HYPERVISOR_net_io_op(&netop) != 0 )
continue;
/* We actually only support up to 4 vifs right now. */
dev->stop = network_close;
dev->get_stats = network_get_stats;
- memcpy(dev->dev_addr, start_info.net_vmac[i], ETH_ALEN);
+ memcpy(dev->dev_addr, netop.u.get_vif_info.vmac, ETH_ALEN);
if ( (err = register_netdev(dev)) != 0 )
{
#include <asm/desc.h>
/* Offsets in start_info structure */
-#define MOD_START 4
-#define MOD_LEN 8
+#define MOD_START 20
+#define MOD_LEN 24
startup_32:
cld
return ret;
}
-static inline int HYPERVISOR_net_io_op(unsigned int op, unsigned int idx)
+static inline int HYPERVISOR_net_io_op(netop_t *op)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_net_io_op),
- "b" (op), "c" (idx) );
+ "b" (op) );
return ret;
}